package fnord.jovian;

import java.awt.*;
import java.util.*;

import javax.swing.*;
import java.awt.event.*;

import fnord.illuminati.card.*;
import fnord.illuminati.order.AttackType;
import fnord.jovian.tango.*;
import fnord.jovian.tango.TheCompassLayout.TheCompassOrientation;
import fnord.jovian.tango.TheWipeTimer.Direction;

public class TheBoard extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2637533871301309937L;

	private enum State{GAME_TREE,GAME_ATTACK,GAME_TRANSFERMONEY, GAME_TRANSFERABLE,
		MENU_INGAME,MENU_SETTINGS,MENU_START,MENU_LOBBY,MENU_CARDACTION,
		MENU_TRANSFERMONEY,MENU_ATTACK,MENU_CONTROL,MENU_TRANSFERABLE};

		private static final Color BACKGROUND = new Color(0,75,0);
		private Vector<TheMenu> _menus = new Vector<TheMenu>();
		private Vector<TheCardTree> _trees;
		private Vector<TheObject> _objects;
		private Vector<TheOrientation> _orientations;
		private TheLayout _layout = new TheCompassLayout(0);
		private boolean _shifting = false, _active = false, _moneyTransferOnly = true;
		private int _player = -1, _showing, _movingTo;
		private TheField _field;
		private TheGUICommunicator _com;
		private TheCard _currentCard, _otherCard;
		private Vector<TheCard> _transferableCollection;
		private Stack<State> _currentState;
		private TheChatPanel _chat;
		private TheStatusPanel _status;
		private TheMapPanel _map;

		public TheBoard(TheGUICommunicator com) {
			super();
			_com = com;
			reset();
		}

		public void reset() {
			this.setLayout(null);
			this.setBackground(BACKGROUND);

			_showing = 0;
			_movingTo = 0;

			_trees = new Vector<TheCardTree>();

			_field = new TheField(this,false);

			_objects = new Vector<TheObject>();
			_orientations = new Vector<TheOrientation>();

			this.addComponentListener(new ResizeListener() );

			_chat = new TheChatPanel(this);
			_status = new TheStatusPanel(this);
			_map = new TheMapPanel(this);

			this.addComponent(new TheArrow(-Math.PI/4.0, new TheShiftListener(3)), TheCompassOrientation.NORTHWEST);
			this.addComponent(new TheArrow(Math.PI/4.0, new TheShiftListener(1)), TheCompassOrientation.NORTHEAST);
			this.addComponent(new TheArrow(0, new TheShiftListener(2)), TheCompassOrientation.NORTH);
			this.addComponent(_chat, TheCompassOrientation.SOUTHWEST);
			this.addComponent(_status, TheCompassOrientation.SOUTH);
			this.addComponent(_map, TheCompassOrientation.SOUTHEAST);

			/*		for (int i = 0; i < _numPlayers; i++) {
			initTree(i);
		}*/

			InputMap im = this.getInputMap(WHEN_IN_FOCUSED_WINDOW);
			ActionMap am = this.getActionMap();
			im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false),"ESCAPE");
			am.put("ESCAPE", new AbstractAction() {
				/**
				 * 
				 */
				private static final long serialVersionUID = -2744413894326139030L;

				public void actionPerformed(ActionEvent arg0) {
					toggleMenu();
					repaint();
				}
			});
			im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false),"LEFT");
			am.put("LEFT", new AbstractAction() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 7831132458309586433L;

				public void actionPerformed(ActionEvent arg0) {
					switchTree(3);
					repaint();
				}
			});
			im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false),"RIGHT");
			am.put("RIGHT", new AbstractAction() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 6730622981277580476L;

				public void actionPerformed(ActionEvent arg0) {
					switchTree(1);
					repaint();
				}
			});
			im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false),"UP");
			am.put("UP", new AbstractAction() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 6730622981277580476L;

				public void actionPerformed(ActionEvent arg0) {
					switchTree(2);
					repaint();
				}
			});
			im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false),"DOWN");
			am.put("DOWN", new AbstractAction() {

				/**
				 * 
				 */
				private static final long serialVersionUID = 6730622981277580476L;

				public void actionPerformed(ActionEvent arg0) {
					switchTree(0);
					repaint();
				}
			});
			_menus.add(new TheGameMenu(this));
			_menus.add(new TheStartMenu(this));
			_menus.add(new TheLobbyMenu(this));
			_menus.add(new TheCardMenu(this));
			_menus.add(new TheAttackMenu(this));
			_menus.add(new TheControlMenu(this));
			_menus.add(new TheMoneyTransferMenu(this));
			_menus.add(new TheTransferableMenu(this));
			_menus.add(new TheSettingsMenu(this));
			_currentState = new Stack<State>();
			_currentState.push(State.GAME_TREE);
			_currentState.push(State.MENU_START);
			TheMouseListener theListener = new TheMouseListener();
			this.addMouseListener(theListener);
			this.addMouseMotionListener(theListener);
			this.addMouseWheelListener(theListener);
			this.grabFocus();
		}

		public int getNumberPlayers() {
			return _trees.size();
		}

		public void setActive(boolean active, int id) {
			_active = active;
			if (_active)
				_status.setPlayer(-1);
			else
				_status.setPlayer(id);
		}

		public void setMoneyTransferOnly(boolean transfer) {
			_moneyTransferOnly = transfer;
		}

		public TheGUICommunicator getCommunicator() {
			return _com;
		}

		public void setTrees(Vector<TheCardTree> trees) {
			_trees = trees;
		}

		public void setField(TheField field) {
			_field = field;
		}

		public void setPlayer(int player) {
			if (_player == -1) {
				_player = player;
				_trees.get(_player).setActive(true);
				_showing = player;
				_movingTo = player;
			}
			else {
				int dif = player - _player;
				if (_showing != -1) {
					_showing = (_showing + dif + _trees.size()) % _trees.size();
					_trees.get(_showing).setActive(true);
				}
				else {
					_field.setActive(true);
				}
				if (_movingTo != -1) {
					_movingTo = (_movingTo + dif + _trees.size()) % _trees.size();
					_trees.get(_movingTo).setActive(true);
				}
				_player = player;
			}
		}

		public void resize() {
			for (int i = 0; i < _menus.size(); i++) {
				_menus.get(i).resize();
			}
			for (int i = 0; i < _trees.size(); i++) {
				_trees.get(i).resize();
			}
		}

		public void toggleMenu() {
			if (_currentState.lastElement() == State.MENU_INGAME)
				_currentState.pop();
			else if (_currentState.lastElement() == State.GAME_TREE){
				_currentState.push(State.MENU_INGAME);
			}
		}

		public void toggleLobby() {
			if (_currentState.lastElement() == State.MENU_LOBBY)
				_currentState.pop();
			else if (_currentState.lastElement() == State.MENU_START){
				_currentState.pop();
				_currentState.push(State.MENU_LOBBY);
			}
		}

		public void startGame() {
			if (_currentState.lastElement() != State.MENU_TRANSFERMONEY) {
				while (_currentState.lastElement() != State.GAME_TREE)
					_currentState.pop();
			}
			repaint();
		}

		public void paint(Graphics g) {
			super.paint(g);

			_layout.layout(_objects, _orientations, 0, 0, getWidth(), getHeight());
			for (int i = 0; i < _objects.size(); i++) {
				_objects.get(i).paint((Graphics2D)g);
			}
			for (int i = 0; i < _trees.size(); i++) {
				_trees.get(i).paint((Graphics2D)g);
			}
			_field.paint((Graphics2D)g);
			switch(_currentState.lastElement()) {
			case GAME_TREE:
				_status.pass(true,"");
				break;
			case GAME_ATTACK:
			case GAME_TRANSFERABLE:
				_status.pass(false,"Attack");
				break;
			case GAME_TRANSFERMONEY:
				_status.pass(false,"Transfer");
				break;
			}
			switch(_currentState.lastElement()) {
			case MENU_START:
				_chat.activatePanel(false);
				_menus.get(1).resize();
				_menus.get(1).paint((Graphics2D)g);
				break;
			case MENU_INGAME:
				_chat.activatePanel(false);
				_menus.get(0).resize();
				_menus.get(0).paint((Graphics2D)g);
				break;
			case MENU_LOBBY:
				_chat.activatePanel(false);
				_menus.get(2).resize();
				_menus.get(2).paint((Graphics2D)g);
				break;
			case MENU_CARDACTION:
				_chat.activatePanel(true);
				_menus.get(3).resize();
				_menus.get(3).paint((Graphics2D)g);
				break;
			case MENU_ATTACK:
				_chat.activatePanel(true);
				_menus.get(4).resize();
				_menus.get(4).paint((Graphics2D)g);
				break;
			case MENU_CONTROL:
				_chat.activatePanel(true);
				_menus.get(5).resize();
				_menus.get(5).paint((Graphics2D)g);
				break;
			case MENU_TRANSFERMONEY:
				_chat.activatePanel(true);
				_menus.get(6).resize();
				_menus.get(6).paint((Graphics2D)g);
				break;
			case MENU_TRANSFERABLE:
				_chat.activatePanel(true);
				_menus.get(7).resize();
				_menus.get(7).paint((Graphics2D)g);
				break;
			case MENU_SETTINGS:
				_chat.activatePanel(false);
				_menus.get(8).resize();
				_menus.get(8).paint((Graphics2D)g);
				break;
			default:
				_chat.activatePanel(true);
			}
			super.paintChildren(g);
		}

		public boolean contains(Point p) {
			switch(_currentState.lastElement()) {
			case GAME_TREE:
				_trees.get(_player).contains(p);
				for (int i = 0; i < _objects.size(); i++) {
					_objects.get(i).contains(p);
				}
				_field.contains(p);
				if (_chat.contains(p))
					_chat.grabFocus();
				else
					grabFocus();
				break;
			case GAME_TRANSFERMONEY:
			case GAME_TRANSFERABLE:
				_trees.get(_player).contains(p);
				for (int i = 0; i < _objects.size(); i++) {
					_objects.get(i).contains(p);
				}
				_field.contains(p);
				if (_chat.contains(p))
					_chat.grabFocus();
				else
					grabFocus();
				break;
			case GAME_ATTACK:
				for (int i = 0; i < _trees.size(); i++) {
					if (i != _player)
						_trees.get(i).contains(p);
				}
				for (int i = 0; i < _objects.size(); i++) {
					_objects.get(i).contains(p);
				}
				_field.contains(p);
				if (_chat.contains(p))
					_chat.grabFocus();
				else
					grabFocus();
				break;
			case MENU_START:
				_menus.get(1).contains(p);
				break;
			case MENU_INGAME:
				_menus.get(0).contains(p);
				break;
			case MENU_CARDACTION:
				_menus.get(3).contains(p);
				if (_chat.contains(p))
					_chat.grabFocus();
				else
					grabFocus();
				break;
			case MENU_ATTACK:
				_menus.get(4).contains(p);
				if (_chat.contains(p))
					_chat.grabFocus();
				else
					grabFocus();
				break;
			case MENU_CONTROL:
				_menus.get(5).contains(p);
				if (_chat.contains(p))
					_chat.grabFocus();
				else
					grabFocus();
				break;
			case MENU_TRANSFERMONEY:
				_menus.get(6).contains(p);
				if (_chat.contains(p))
					_chat.grabFocus();
				else
					grabFocus();
				break;
			case MENU_TRANSFERABLE:
				_menus.get(7).contains(p);
				if (_chat.contains(p))
					_chat.grabFocus();
				else
					grabFocus();
				break;
			case MENU_SETTINGS:
				_menus.get(8).contains(p);
				break;
			default:		
			}

			return super.contains(p);
		}

		public boolean containsClick(Point p) {
			if (!_shifting) {
				switch(_currentState.lastElement()) {
				case GAME_TREE:
					if (_active)
						_trees.get(_player).containsClick(p);
					for (int i = 0; i < _objects.size(); i++) {
						_objects.get(i).containsClick(p);
					}
					break;
				case GAME_TRANSFERMONEY:
				case GAME_TRANSFERABLE:
					_trees.get(_player).containsClick(p);
					for (int i = 0; i < _objects.size(); i++) {
						_objects.get(i).containsClick(p);
					}
					break;
				case GAME_ATTACK:
					for (int i = 0; i < _trees.size(); i++) {
						if (i != _player)
							_trees.get(i).containsClick(p);
					}
					for (int i = 0; i < _objects.size(); i++) {
						_objects.get(i).containsClick(p);
					}
					_field.containsClick(p);
					break;
				case MENU_START:
					_menus.get(1).containsClick(p);
					break;
				case MENU_INGAME:
					_menus.get(0).containsClick(p);
					break;
				case MENU_CARDACTION:
					_menus.get(3).containsClick(p);
					break;
				case MENU_ATTACK:
					_menus.get(4).containsClick(p);
					break;
				case MENU_CONTROL:
					_menus.get(5).containsClick(p);
					break;
				case MENU_TRANSFERMONEY:
					_menus.get(6).containsClick(p);
					break;
				case MENU_TRANSFERABLE:
					_menus.get(7).containsClick(p);
					break;
				case MENU_SETTINGS:
					_menus.get(8).containsClick(p);
					break;
				default:		
				}
			}

			return super.contains(p);
		}

		public boolean containsDrag(Point p) {
			if (!_shifting) {
				switch(_currentState.lastElement()) {
				case GAME_TREE:
					if (_active) {
						_trees.get(_player).containsDrag(p);
					}
					for (int i = 0; i < _objects.size(); i++) {
						_objects.get(i).containsDrag(p);
					}
					break;
				case GAME_TRANSFERMONEY:
				case GAME_TRANSFERABLE:
					_trees.get(_player).containsDrag(p);
					for (int i = 0; i < _objects.size(); i++) {
						_objects.get(i).containsDrag(p);
					}
					break;

				case GAME_ATTACK:
					for (int i = 0; i < _trees.size(); i++) {
						if (i != _player)
							_trees.get(i).containsDrag(p);
					}
					for (int i = 0; i < _objects.size(); i++) {
						_objects.get(i).containsDrag(p);
					}
					break;
				case MENU_START:
					_menus.get(1).containsDrag(p);
					break;
				case MENU_INGAME:
					_menus.get(0).containsDrag(p);
					break;
				case MENU_CARDACTION:
					_menus.get(3).containsDrag(p);
					break;
				case MENU_ATTACK:
					_menus.get(4).containsDrag(p);
					break;
				case MENU_CONTROL:
					_menus.get(5).containsDrag(p);
					break;
				case MENU_TRANSFERMONEY:
					_menus.get(6).containsDrag(p);
					break;
				case MENU_TRANSFERABLE:
					_menus.get(7).containsDrag(p);
					break;
				case MENU_SETTINGS:
					_menus.get(8).containsDrag(p);
					break;
				default:
				}
			}
			return super.contains(p);

		}

		public boolean containsUp(Point p) {
			if (!_shifting) {
				switch(_currentState.lastElement()) {
				case GAME_TREE:
					if (_active) {
						_trees.get(_player).containsUp(p);
					}
					for (int i = 0; i < _objects.size(); i++) {
						_objects.get(i).containsUp(p);
					}
					break;
				case GAME_TRANSFERMONEY:
				case GAME_TRANSFERABLE:
					_trees.get(_player).containsUp(p);
					for (int i = 0; i < _objects.size(); i++) {
						_objects.get(i).containsUp(p);
					}
					break;

				case GAME_ATTACK:
					for (int i = 0; i < _trees.size(); i++) {
						if (i != _player)
							_trees.get(i).containsUp(p);
					}
					for (int i = 0; i < _objects.size(); i++) {
						_objects.get(i).containsUp(p);
					}
					_field.containsUp(p);
					break;
				case MENU_START:
					_menus.get(1).containsUp(p);
					break;
				case MENU_INGAME:
					_menus.get(0).containsUp(p);
					break;
				case MENU_CARDACTION:
					_menus.get(3).containsUp(p);
					break;
				case MENU_ATTACK:
					_menus.get(4).containsUp(p);
					break;
				case MENU_CONTROL:
					_menus.get(5).containsUp(p);
					break;
				case MENU_TRANSFERMONEY:
					_menus.get(6).containsUp(p);
					break;
				case MENU_TRANSFERABLE:
					_menus.get(7).containsUp(p);
					break;
				case MENU_SETTINGS:
					_menus.get(8).containsUp(p);
					break;
				default:
				}
			}
			return super.contains(p);
		}

		private class TheMouseListener implements MouseWheelListener, MouseListener, MouseMotionListener {

			public void mouseWheelMoved(MouseWheelEvent e) {}
			public void mousePressed(MouseEvent e) {
				containsClick(e.getPoint());
				repaint();
			}
			public void mouseReleased(MouseEvent e) {
				containsUp(e.getPoint());
				repaint();
			}
			public void mouseDragged(MouseEvent e) {
				containsDrag(e.getPoint());
				repaint();
			}
			public void mouseClicked(MouseEvent e) {
				containsClick(e.getPoint());
				repaint();
			}
			public void mouseEntered(MouseEvent e) {}
			public void mouseExited(MouseEvent e) {}
			public void mouseMoved(MouseEvent e) {
				contains(e.getPoint());
				repaint();
			}

		}

		public void containAction() {}

		public void clickAction() {}

		public void upAction() {}

		public void outAction() {}

		public void setLocation(double x, double y) {}

		public void setSize(double w, double h) {}

		public void setTheLayout(TheLayout layout) {
			_layout = layout;
		}

		public void addComponent(TheObject o) {
			_objects.add(o);
		}

		public void addComponent(TheObject o, TheOrientation or) {
			_objects.add(o);
			_orientations.add(or);
		}

		public void shift(double x, double y) {
			contains(MouseInfo.getPointerInfo().getLocation());
			if (_showing == -1)
				_field.shift(x,y);
			else
				_trees.get(_showing).shift(x,y);
			if (_movingTo == -1)
				_field.shift(x,y);
			else
				_trees.get(_movingTo).shift(x,y);
		}

		public void shift(double rad) {
			contains(MouseInfo.getPointerInfo().getLocation());
			_trees.get(_movingTo).shift(rad);
			_trees.get(_showing).shift(rad);
		}

		public void finishShift() {
			if (_showing == -1)
				_field.setActive(false);
			else {
				_trees.get(_showing).resize();
				_trees.get(_showing).move(0);
				_trees.get(_showing).setActive(false);
			}
			_showing = _movingTo;
			_shifting = false;
			_map.setCurrent(_showing);
		}

		public void switchTree(int dir) {
			if (!_shifting && _currentState.lastElement() != State.MENU_START && _currentState.lastElement() != State.MENU_LOBBY) {
				TheWipeTimer timer;
				switch(dir) {
				case 0:
					if (_showing != _player) {
						_shifting = true;
						_movingTo = _player;
						_trees.get(_movingTo).setActive(true);
						_trees.get(_movingTo).move(0,getHeight());
						timer = new TheWipeTimer(this, Direction.UP, 0.5);
						timer.start();
					}
					break;
				case 1:
					if (_showing != -1) {
						_shifting = true;
						_movingTo = (_showing + _trees.size() - 1) % _trees.size();
						_trees.get(_movingTo).setActive(true);
						_trees.get(_movingTo).resize();
						_trees.get(_movingTo).move(-Math.PI/2.0);
						timer = new TheWipeTimer(this, Direction.RIGHT, 0.5);
						timer.start();
					}
					break;
				case 2:
					if (_showing != -1) {
						_shifting = true;
						_movingTo = -1;
						_field.setActive(true);
						_field.move(0,-getHeight());
						timer = new TheWipeTimer(this, Direction.DOWN, 0.5);
						timer.start();
					}
					break;
				case 3:
					if (_showing != -1) {
						_shifting = true;
						_movingTo = (_showing + 1) % _trees.size();
						_trees.get(_movingTo).setActive(true);
						_trees.get(_movingTo).move(Math.PI/2.0);
						timer = new TheWipeTimer(this, Direction.LEFT, 0.5);
						timer.start();
					}
					break;
				}
			}
		}

		public void switchTree(int dir, int to) {
			if (!_shifting && _currentState.lastElement() != State.MENU_START && _currentState.lastElement() != State.MENU_LOBBY) {
				TheWipeTimer timer;
				if (_showing == -1) {
					_shifting = true;
					_movingTo = to;
					_trees.get(_movingTo).setActive(true);
					_trees.get(_movingTo).move(0,getHeight());
					timer = new TheWipeTimer(this, Direction.UP, 0.3);
					timer.start();
				}
				else {
					switch(dir) {
					case 0:
						_shifting = true;
						_movingTo = to;
						_trees.get(_movingTo).setActive(true);
						_trees.get(_movingTo).move(-Math.PI/2.0);
						timer = new TheWipeTimer(this, Direction.RIGHT, 0.5);
						timer.start();
						break;
					case 1:
						_shifting = true;
						_movingTo = to;
						_trees.get(_movingTo).setActive(true);
						_trees.get(_movingTo).move(Math.PI/2.0);
						timer = new TheWipeTimer(this, Direction.LEFT, 0.5);
						timer.start();
						break;
					}
				}
			}
		}

		private class TheShiftListener implements TheListener {
			private int _s;
			public TheShiftListener(int i) {
				_s = i;
			}
			public void doAction() {
				switchTree(_s);
				repaint();
			}
		}

		private class ResizeListener implements ComponentListener {

			public void componentResized(ComponentEvent arg0) {
				for (int i = 0; i < _trees.size(); i++ ) {
					_trees.get(i).resize();
				}
			}

			public void componentHidden(ComponentEvent arg0) {}
			public void componentMoved(ComponentEvent arg0) {}
			public void componentShown(ComponentEvent arg0) {}

		}

		public void cardAction(TheCard card) {
			if (_moneyTransferOnly) {
				if (_currentState.lastElement() == State.GAME_TRANSFERMONEY)
					transferAction(card);
				if (_currentState.lastElement() == State.GAME_TREE){
					_currentCard = card;
					_currentState.push(State.MENU_CARDACTION);
					((TheCardMenu)(_menus.get(3))).showTransferAttack(false, card.getCard().getMoney() > 0);
				}
			}
			else {
				if (_currentState.lastElement() == State.GAME_TRANSFERMONEY)
					transferAction(card);
				if (_currentState.lastElement() == State.GAME_TREE){
					_currentCard = card;
					_currentState.push(State.MENU_CARDACTION);
					((TheCardMenu)(_menus.get(3))).showTransferAttack(card.getCard().getOpenDirections().length > 0
							&& !card.getCard().getUsed(), card.getCard().getMoney() > 0);
				}
			}
		}

		public void cancelAction() {
			_status.pass(true,"");
			if (_currentCard != null) {
				_currentCard.setUsed(false);
				_currentCard = null;
			}
			_otherCard = null;
			_currentState = new Stack<State>();
			_currentState.push(State.GAME_TREE);
		}

		public void attackAction(TheCard card) {
			_otherCard = card;
			if (attack()) {
				_transferableCollection = new Vector<TheCard>();
				_currentCard.setUsed(true);
				if (_trees.get(_player).transferable(_trees.get(_player).root())) {
					_currentState.pop();
					_currentState.push(State.MENU_TRANSFERABLE);
				}
				else
					continueAttack();
			}
		}

		public void addTransferable() {
			if (_currentState.lastElement() == State.MENU_TRANSFERABLE)
				_currentState.push(State.GAME_TRANSFERABLE);
		}

		public void transferableAction(TheCard card) {
			if (transferable() && !card.getCard().getUsed()) {
				_transferableCollection.add(card);
				card.setUsed(true);
				_currentState.pop();
				if (!_trees.get(_player).transferable(_trees.get(_player).root()))
					continueAttack();
			}
		}

		public boolean transferable() {
			return _currentState.lastElement() == State.GAME_TRANSFERABLE;
		}

		public boolean attack() {
			return _currentState.lastElement() == State.GAME_ATTACK;
		}

		public void continueAttack() {
			if (_currentState.lastElement() == State.MENU_TRANSFERABLE)
				_currentState.pop();
			((TheAttackMenu)(_menus.get(4))).showNeutral(_otherCard.getParent() != null);
			_currentState.push(State.MENU_ATTACK);
		}

		public void sendAttack(AttackType type) {
			_com.sendAttackOrder(_currentCard, _otherCard, type, null, _transferableCollection);
			if (_currentCard != null) {
				_currentCard.setUsed(true);
				_currentCard = null;
			}
			_otherCard = null;
			_currentState.pop();
		}

		public void sendAttack(Connection con) {
			_com.sendAttackOrder(_currentCard, _otherCard, AttackType.CONTROL, con, _transferableCollection);
			if (_currentCard != null) {
				_currentCard.setUsed(true);
				_currentCard = null;
			}
			if (_otherCard != null) {
				_otherCard.setUsed(true);
				_otherCard = null;
			}
			_currentState.pop();
		}

		public void showControl() {
			if (_currentState.lastElement() == State.MENU_ATTACK) {
				((TheControlMenu)(_menus.get(5))).setButtons(_currentCard.getCard().getOpenDirections());
				_currentState.pop();
				_currentState.push(State.MENU_CONTROL);
			}
		}

		public void attacking() {
			if (_currentState.lastElement() == State.MENU_CARDACTION) {
				_currentState.pop();
				_currentState.push(State.GAME_ATTACK);
			}
		}

		public void transferringMoney() {
			if (_currentState.lastElement() == State.MENU_CARDACTION) {
				_currentState.pop();
				_currentState.push(State.GAME_TRANSFERMONEY);
			}
		}

		public void transferAction(TheCard card) {
			_otherCard = card;
			if (_currentState.lastElement() == State.GAME_TRANSFERMONEY) {
				((TheMoneyTransferMenu)(_menus.get(6))).setTransfer(_currentCard, _otherCard);
				_currentState.pop();
				_currentState.push(State.MENU_TRANSFERMONEY);
			}
		}

		public void transferMoney(int amt) {
			_com.sendMoneyOrder(_currentCard, _otherCard, amt);
			_currentState.pop();
			_currentCard = null;
			_otherCard = null;
		}

		public void spendMoney(int amt, GroupCard to) {
			_com.spendMoney(_trees.get(_player).root().getCard(), to, amt);
			_currentState.pop();
		}

		public void setSpendMoneyOnly(boolean onlySpendMoney,
				GroupCard attackingCard, GroupCard defendingCard) {
			if (onlySpendMoney && _active) {
				((TheMoneyTransferMenu)(_menus.get(6))).setMoney(attackingCard, defendingCard);
				_currentState.push(State.MENU_TRANSFERMONEY);
				repaint();
			}

		}

		public void toggleSettings() {
			if (_currentState.lastElement() == State.MENU_INGAME || _currentState.lastElement() == State.MENU_START) {
				_currentState.push(State.MENU_SETTINGS);
				((TheSettingsMenu)(_menus.get(8))).setActive(true);
			}
			else if (_currentState.lastElement() == State.MENU_SETTINGS) {
				_currentState.pop();
				((TheSettingsMenu)(_menus.get(8))).setActive(false);
			}
		}

		public void sendChat(String chat) {
			_com.sendChat(chat);
		}

		public void receiveChat(String chat) {
			_chat.addText(chat);
		}

		public void pass() {
			_com.pass();
		}

		public void setStatus(String notification) {
			_status.setStatus(notification);
		}

		public void setMapTreesField(Vector<TheCardTree> miniTrees, TheField field) {
			_map.setupMap(miniTrees,field,_player,_showing);
		}

}